package com.itheima.d06_springframework;

import com.itheima.d06_springframework.annotation.Autowired;
import com.itheima.d06_springframework.annotation.Controller;
import com.itheima.d06_springframework.annotation.Repository;
import com.itheima.d06_springframework.annotation.Service;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 自定义Spring 的容器工程类：IOC容器
 *      创建对象/管理对象的容器
 *
 * 1.项目启动，扫描所有类，创建对象（IOC），设置属性（DI）
 * 2.预加载的思想：空间换时间，操作效率高
 */
public class BeanFactory {

    //1.定义集合，存储所有创建好的对象
    public static Map<String,Object> beanMap = new HashMap<>();

    //2.静态代码块，创建对象，并放入集合中
    static {

        try {
            //1.扫描当前项目中所有类
            List<String> classPathList = Arrays.asList(
                    "com.itheima.d06_springframework.controller.StudentController",
                    "com.itheima.d06_springframework.dao.StudentDao",
                    "com.itheima.d06_springframework.service.StudentService",
                    "com.itheima.d06_springframework.test.Test",
                    "com.itheima.d06_springframework.BeanFactory");

            //2.获取所有类的Class对象
            List<Class> classList = new ArrayList<>();
            for (String className : classPathList) {
                try {
                    Class<?> cla = Class.forName(className);
                    classList.add(cla);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }

            //3.遍历所有类，判断类上是否有指定的注解
            for (Class<?> cla : classList) {
                //判断类上是否添加了：@Controller/@Service/@Repository
                if(cla.isAnnotationPresent(Controller.class)
                    || cla.isAnnotationPresent(Service.class)
                    ||  cla.isAnnotationPresent(Repository.class)){
                    //4.反射创建当前类的对象
                    //spring框架：默认使用的对象名称，类名首字母小写
                    String name = cla.getName();  // com.itheima.d06_springframework.controller.StudentController
                    name = name.substring(name.lastIndexOf(".")+1);  //StudentController
                    name = name.substring(0,1).toLowerCase() + name.substring(1); //studentController

                    Object obj = cla.newInstance();  //spring框架：默认调用的无参构造方法，创建对象
                    beanMap.put(name, obj);
                }

            }

            //4.设置属性值
            for (Map.Entry<String, Object> entry : beanMap.entrySet()) {
                Object instance = entry.getValue(); //获取bean对象
                Class<?> clazz = instance.getClass(); //获取bean对象对应的字节码

                //5.获取当前对象的所有Field属性
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    //6.检查当前属性对象上是否添加的指定的AutoWired注解
                    if(field.isAnnotationPresent(Autowired.class)){
                        //7.获取属性名称
                        String name = field.getName();

                        //8.从集合中获取属性值：spring框架能够设置的属性一定要在集合中存在
                        Object valueObj = beanMap.get(name);

                        if(valueObj != null ){
                            //9.反射的方式设置属性值
                            field.setAccessible(true);
                            field.set(instance,valueObj);
                        }
                    }
                }
            }


        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    //3.提供获取bean的方法
    public static Object getBean(String name){
        return beanMap.get(name);
    }
}


















